package com.mypaper.schedule;

import com.mypaper.elem.IntElement;
import com.mypaper.elem.LinkedListNode;
import com.mypaper.elem.ScheduleElement;
import com.mypaper.elem.ScheduleNode;
import com.mypaper.elem.TaskNode;
import com.mypaper.list.AdjoinTable;
import com.mypaper.list.ListPriority;



public class EAMDSchedule {
	protected ScheduleAlgorithm SA;
	protected AdjoinTable AT;
	
	public EAMDSchedule(AdjoinTable AT, ScheduleAlgorithm SA){
		this.SA=SA;
		this.AT=AT;		
	}
	
	public void EAMD_Schedule(float[][] edgeWeight, ListPriority priorRever){
		int dupCopyIndex=0;
		int currentProc=0;
		float startT=0;
		float endT=0;
		boolean flag=true;
		int currChildIndex=0;
		TaskNode currentTask=new TaskNode();
		currentTask=priorRever.first;//优先级队列第一个任务
		LinkedListNode currentChild=new LinkedListNode();		
		while(currentTask!=null){
			if(SA.reliedDup[currentTask.info.index]!=-1){
				dupCopyIndex=SA.reliedDup[currentTask.info.index];
				currentProc=SA.assiProc2Task[currentTask.info.index];
				startT=SA.MEST[dupCopyIndex][currentProc];
				endT=SA.MEFT[dupCopyIndex][currentProc];
				
				currentChild=AT.vertexChild[dupCopyIndex].first;//Duplication任务的第一个孩子
				flag=true;
				while(currentChild!=null){			
					IntElement currentChildIndex=(IntElement)currentChild.info;
					currChildIndex=currentChildIndex.num;
					if(SA.assiProc2Task[currChildIndex]!=currentProc){
						//复制任务的子节点与复制任务处于不同处理器上
						if(endT+edgeWeight[dupCopyIndex][currChildIndex]>SA.AST[currChildIndex]){
							flag=false;
							break;
						}
					}
						//复制任务的子节点与复制任务处于同一处理器上不处理		
					currentChild=currentChild.next;
				}
				if(flag==true){
					//原版本可以删除
					SA.assiProc2Task[dupCopyIndex]=(short) currentProc;
					SA.AST[dupCopyIndex]=startT;
					SA.AFT[dupCopyIndex]=endT;
					ScheduleNode perTask=SA.scheduleResults.first;
					while(perTask!=null){
						ScheduleElement perTaskSchedule=perTask.info;
						if(perTaskSchedule.taskID==dupCopyIndex&&perTaskSchedule.processorID!=currentProc){
							perTask=perTask.next;
							SA.scheduleResults.deleteNode(perTaskSchedule);	
							if(SA.reliedDup[perTaskSchedule.taskID]!=-1){
								//将该删除任务依赖的复制版本也删除
								ScheduleNode currentTaskDup=SA.scheduleResults.first;
								while(currentTaskDup!=null&&!currentTaskDup.info.equals(SA.reliedDup[perTaskSchedule.taskID], perTaskSchedule.processorID)){
									currentTaskDup=currentTaskDup.next;
								}
								if(currentTaskDup!=null){
									SA.scheduleResults.deleteNode(currentTaskDup.info);
									SA.reliedDup[perTaskSchedule.taskID]=-1;
									
								}	
								
							}
							perTask=SA.scheduleResults.first;
						}else
							perTask=perTask.next;
					}
				}
				
			}
			currentTask=currentTask.next;
		}
		//SA.scheduleResults.print();
	}
	
	public float energyCal(int procNum){
		float enerSum=0;
        float timeSum=0;	
        float totalTime=0;
        float power=(float)0.925, idlePower=(float)0.260;
        boolean[] flag=new boolean[procNum];
        float[] procTermTime=new float[procNum];
        ScheduleNode currentTask=SA.scheduleResults.first;
		while(currentTask!=null){
			ScheduleElement perTask=currentTask.info;
			if(flag[perTask.processorID]!=true)
				flag[perTask.processorID]=true;
			if(perTask.endTime>procTermTime[perTask.processorID])
				procTermTime[perTask.processorID]=perTask.endTime;
			timeSum+=(perTask.endTime-perTask.startTime);
			currentTask=currentTask.next;
		}
		
		for(int i=0; i<procNum; i++){
			System.out.println("End time of processor "+i+" is "+procTermTime[i]);
			totalTime+=procTermTime[i];
		}
		
		System.out.println("idletime： "+(totalTime-timeSum));
		System.out.println("busytime： "+timeSum);
		enerSum=timeSum*power+(totalTime-timeSum)*idlePower;
		return enerSum;
	}
	
	
	public float makespan(){
		float curr=0;
		ScheduleNode currentTask=SA.scheduleResults.first;
		while(currentTask!=null){
			if(curr<currentTask.info.endTime)
				curr=currentTask.info.endTime;
			currentTask=currentTask.next;
		}
		return curr;
	}
}
